home *** CD-ROM | disk | FTP | other *** search
- /* Meter.c - display, drive and control a meter with set point.
- Useage: add 'Meter.c' to your project, and #include "Meter.h" in any
- file that refers to the functions below. Add 'Math' and
- #include <math.h> if you don't hand-load the sineTable[].
- - the main purpose here is to show how the Control Manager works,
- so we'll use functional equivalents of most of the Control Manager
- routines listed in Inside Macintosh vol 1 pages 309 - 338 rather than
- creating a new kind of control. In general, "Control" in IM is replaced
- by "Meter" here; for example, if you're interested in
- how NewControl() works see NewMeter() below. See MeterProc() in MeterMain.c
- for an action procedure that is called by TrackMeter() to drive the
- set point indicator up and down. Fancy stuff requiring external user-defined
- resources is not included (no GetNewMeter()), nor is a default action Proc
- supported (always call TrackMeter() with your action Proc or 0L). Two other
- differences that no one should mind - all functions are 'C' rather than 'pascal',
- and all value parameters are long.
- - meterValue refers to the set point value, which is normally under user control,
- and can be set by SetMtrValue().
- - needleValue refers to current input to the meter, displayed by the needle
- and NOT normally under user's control, set by SetNeedleValue().
- - the digital display normally shows needleValue unless mouse is down in
- meter background (simple equivalent of control "thumb").
- - for a more detailed look at controlling what happens when the mouse is
- in an indicator see ThumbControl() in MeterMain.c.
- - the arrow and paging parts appear as small and large triangles (defined as
- polygons), with the standard part codes.
- - meter handles are linked to the owning windows' refCon field. If you want to
- use this field for something else, change the refCon references below in NewMeter(),
- DisposeMeter(), KillMeters(), DrawMeters(), and FindMeter().
- */
-
- /* Do not include Meter.h, but DO #include <MacHeaders> either
- explicitly here or by setting the "<MacHeaders>" option */
-
- /* math.h is needed for the sineTable[] array, otherwise hand-load it. */
- #define _ERRORCHECK_
- int errno;
- #include <math.h>
-
- /* special partCode for meter, everything but the four up and down arrows.
- A meter has no true thumb - the set point indicator is a skinny rotating
- target, and too dangerous to grab if the meter is being used for closed-
- loop control. "Track and hilite the background" just means show the set
- point value in the display rather than the current needle value while the
- mouse is down.*/
- #define inBackground 24
-
- #define NULL 0L
- #define HASMETER 'qwer' /* arbitrary long ID, used by ValidMeter() */
-
- /* Some #defines to vary the appearance of the meter. Since meters are
- complicated beasts to draw, be prepared to fine-tune the drawing code
- as well if you explore different looks! */
- #define MINWIDTH 48 /* min. usable meter width */
- #define TVHRATIO 1400L /* black rounded rect height/width, times 1000 */
- #define TITLEHEIGHT 24 /* height of title box below meter proper, plus 4 */
- /* given width of meter = w, total height is (w*TVHRATIO)/1000 + TITLEHEIGHT */
- #define TEXTVOFFSET 4 /* to centre 12 pt text in the display box */
- #define INNERPCT 94L /* used for defining needle and set point
- lengths as a % of dial radius */
- #define HALFSETWIDTH 1 /* half width of set point indicator */
- #define CENTRERADIUS 3 /* radius of meter's little centre circle */
- #define PGPOLYHEIGHT 3000L /* times 1000, keep it between 1000 and 3000 */
- #define INCPOLYHEIGHT 2000L
- /* --POLYHEIGHT is ratio of height to width of set point control
- triangles times 1000 - try 1000,1414,1732,2000,3000. */
- #define NUMTICKS 11 /* number of major position ticks around circumference */
- #define NUMMINORTICKS 51 /* NUMMINORTICKS includes the NUMTICKS. */
- #define HALFNEEDLERATIO 8 /* dial radius/HALFNEEDLERATIO = halfNeedleWidth */
- #define MINDIGITS 3 /* minimum number of digits to display */
- #define MAXDIGITS 5 /* maximum number of digits to display */
- /* The digital display will show at least MINDIGITS for small meters, and at most
- MAXDIGITS for large meters. See ShowValue(), AdjustDisplay(), and SetDisplayDivisor()
- for details. As a nicety, you should update the meter title to reflect the actual
- units displayed (eg if input is Volts and displayDivisor is 10, the meter name should
- be something like "Volts / 10" */
-
- static int sineTable[91]; /* set up by InitMeters() */
-
- struct MeterRecord
- {
- struct MeterRecord **nextMeter; /* or NULL */
- WindowPtr meterOwner;
- Rect meterRect; /* includes title */
- Byte meterVis;
- Byte meterHilite;
- long meterValue, meterMin, meterMax, needleValue;
- /*ProcPtr meterAction; - not implemented */
- long meterRfCon;
- char title[32]; /* pascal format, length byte first */
- /* some additional fields not found in a control record */
- Rect incDownRect, incUpRect, pageDownRect, pageUpRect;
- Rect displayRect; /* digital display */
- long displayDivisor; /* power of ten */
- int needleShort, needleLong, halfNeedleWidth;
- int setShort, setLong, halfSetWidth;
- PicHandle backgroundH;
- PolyHandle incUpH, incDownH, pageUpH, pageDownH; /* triangles */
- Point dialCentre;
- long hasMeterID; /* = HASMETER for a meter */
- };
- typedef struct MeterRecord MeterRecord;
- typedef MeterRecord *MeterPtr;
- typedef MeterRecord **MeterHandle;
-
- typedef void (*voidPtr)(); /* true C equiv. of procPtr */
-
- /* Functions defined in this file */
-
- /* external interface, mostly like Control Manager */
- /* Control Manager equivalents */
- MeterHandle NewMeter(WindowPtr, Rect*, char*, Boolean, long, long, long, long);
- void DisposeMeter(MeterHandle);
- void KillMeters(WindowPtr);
- void SetMTitle(MeterHandle, char*);
- void GetMTitle(MeterHandle, char*);
- void HideMeter(MeterHandle);
- void ShowMeter(MeterHandle);
- void DrawMeters(WindowPtr);
- void HiliteMeter(MeterHandle, int);
- int FindMeter(Point, WindowPtr, MeterHandle*);
- int TrackMeter(MeterHandle, Point, voidPtr);
- int TestMeter(MeterHandle, Point);
- void MoveMeter(MeterHandle, int, int);
- void DragMeter(MeterHandle, Point, Rect*, Rect*, int);
- void SizeMeter(MeterHandle, int); /* note proportions are fixed */
- void SetMtrValue(MeterHandle, long); /* use this to move the set point */
- long GetMtrValue(MeterHandle);
- void SetMtrMin(MeterHandle, long);
- long GetMtrMin(MeterHandle);
- void SetMtrMax(MeterHandle, long);
- long GetMtrMax(MeterHandle);
- void SetMRefCon(MeterHandle, long);
- long GetMRefCon(MeterHandle);
- /* Special meter functions */
- void SetNeedleValue(MeterHandle, long); /* use this to move the needle */
- long GetNeedleValue(MeterHandle);
- long GetDisplayDivisor(MeterHandle);
- Boolean ValidMeter(MeterHandle);
- int GetMaxTitlePixels(MeterHandle); /* displayable title width */
- void MeterSnapshot(MeterHandle); /* draws meter to thePort
- rather than meter's owning window */
-
- /* support functions used in this file only */
- void InitMeters(void);
- void CreateMeterBackground(MeterHandle);
- void DrawMeterBackground(MeterHandle);
- void DrawMeterTitle(MeterHandle);
- void DrawTriangle(MeterHandle, int);
- void DrawNeedle(MeterHandle);
- void DrawSet(MeterHandle);
- void ShowValue(MeterHandle, Boolean);
- void DrawInactiveMeter(MeterHandle);
- void AdjustDisplay(MeterHandle);
- void SetDisplayDivisor(MeterHandle);
- void GetSinAndCos(int, long*, long*);
-
- /* New meter handles are linked to the window's refCon field. Meter proportions are fixed;
- height is determined from width, and boundRect.bottom is ignored. There is no default
- action procedure. Titles are truncated on the right.*/
- MeterHandle NewMeter(wPtr, boundRect, title, visible, meterValue, meterMin, meterMax, meterRfCon)
- WindowPtr wPtr;
- Rect *boundRect;
- char *title;
- Boolean visible;
- long meterValue, meterMin, meterMax;
- long meterRfCon;
- {
- int i,j;
- MeterHandle mH, tempMH;
- MeterPtr mPtr;
- WindowPeek wPk = (WindowPeek)wPtr;
- char *titlePtr;
-
- /* Initialize sine table if necessary. */
- if (sineTable[45] == 0) /* should be 707 by the way */
- InitMeters();
- /* Allocate and attach a new meter record. */
- mH = (MeterHandle)NewHandle(sizeof(MeterRecord));
- if (MemError() != noErr)
- return(NULL);
- mPtr = *mH;
- mPtr->meterOwner = wPtr;
- mPtr->nextMeter = NULL;
- mPtr->hasMeterID = HASMETER;
- /* refCon of WindowRecord holds first MeterHandle. */
- /* New meters are inserted at beginning of list. */
- tempMH = (MeterHandle)(wPk->refCon);
- wPk->refCon = (long)mH;
- if (tempMH && ((**tempMH).hasMeterID == HASMETER))
- mPtr->nextMeter = tempMH;
- /* Fill in the easy fields. */
- mPtr->meterVis = visible;
- mPtr->meterHilite = 0; /* active */
- /* meterMin <= meterValue <= meterMax */
- if (meterMax < meterMin)
- {
- DisposeMeter(mH);
- return(NULL);
- }
- if (meterValue < meterMin)
- meterValue = meterMin;
- if (meterValue > meterMax)
- meterValue = meterMax;
- if (meterMin == meterMax)
- (**mH).meterHilite = 255; /* inactive - see IM 1-327 */
- mPtr->meterValue = meterValue;
- mPtr->meterMin = meterMin;
- mPtr->meterMax = meterMax;
- mPtr->meterRfCon = meterRfCon;
- mPtr->needleValue = meterMin; /* default value */
- j = title[0];
- if (j > 31)
- j = 31;
- titlePtr = mPtr->title;
- for (i = 0; i <= j; ++i)
- *titlePtr++ = *title++;
- (**mH).meterRect = *boundRect;
- (**mH).halfSetWidth = HALFSETWIDTH;
- /* Do the grunt work. */
- CreateMeterBackground(mH);
- /* Draw meter if visible. */
- if (visible)
- {
- (**mH).meterVis = FALSE; /* forces drawing */
- ShowMeter(mH);
- }
- return(mH);
- } /* end NewMeter() */
-
- void DisposeMeter(mH)
- MeterHandle mH;
- {
- Rect tempRect;
- PicHandle tempPH;
- PolyHandle tempPoly;
- MeterHandle tMH;
- GrafPtr savePort;
-
- if (!ValidMeter(mH)) return;
- GetPort(&savePort);
- SetPort((**mH).meterOwner);
- tempPH = (**mH).backgroundH;
- KillPicture(tempPH);
- tempPoly = (**mH).incUpH;
- KillPoly(tempPoly);
- tempPoly = (**mH).incDownH;
- KillPoly(tempPoly);
- tempPoly = (**mH).pageUpH;
- KillPoly(tempPoly);
- tempPoly = (**mH).pageDownH;
- KillPoly(tempPoly);
- tempRect = (**mH).meterRect;
- EraseRect(&tempRect);
- InvalRect(&tempRect);
- /* Unlink the meter. */
- tMH = (MeterHandle)(((WindowPeek)((**mH).meterOwner))->refCon);
- if (tMH != mH)
- {
- while ((**tMH).nextMeter != mH)
- tMH = (**tMH).nextMeter;
- (**tMH).nextMeter = (**mH).nextMeter;
- }
- else
- ((WindowPeek)((**mH).meterOwner))->refCon = (long)((**mH).nextMeter);
- DisposHandle((Handle)mH);
- SetPort(savePort);
- } /* end DisposeMeter() */
-
- void KillMeters(wPtr)
- WindowPtr wPtr;
- {
- WindowPeek wPk = (WindowPeek)wPtr;
-
- while (wPk->refCon && ((**((MeterHandle)(wPk->refCon))).hasMeterID == HASMETER))
- DisposeMeter((MeterHandle)(wPk->refCon));
- } /* end KillMeters() */
-
- void SetMTitle(mH, title)
- MeterHandle mH;
- char *title;
- {
- int j, i = title[0];
- GrafPtr savePort;
- Rect tempRect;
-
- if (!ValidMeter(mH)) return;
- if (i > 31)
- i = 31;
- if (i)
- {
- for (j = 0; j <= i; ++j)
- (**mH).title[j] = title[j];
- GetPort(&savePort);
- SetPort((**mH).meterOwner);
- DrawMeterTitle(mH);
- SetPort(savePort);
- }
- } /* end SetMTitle() */
-
- void GetMTitle(mH, title)
- MeterHandle mH;
- char *title;
- {
- int j, i = (**mH).title[0];
- if (!ValidMeter(mH))
- {
- title[0] = 0;
- return;
- }
- for (j = 0; j <=i; ++j)
- title[j] = (**mH).title[j];
- } /* end GetMTitle() */
-
- void HideMeter(mH)
- MeterHandle mH;
- {
- Rect tempRect;
- GrafPtr savePort;
-
- if (!ValidMeter(mH)) return;
- if (!(**mH).meterVis) return;
- GetPort(&savePort);
- SetPort((**mH).meterOwner);
- (**mH).meterVis = FALSE;
- tempRect = (**mH).meterRect;
- EraseRect(&tempRect);
- InvalRect(&tempRect);
- SetPort(savePort);
- } /* end HideMeter() */
-
- void ShowMeter(mH)
- MeterHandle mH;
- {
- int i;
- GrafPtr savePort;
-
- if (!ValidMeter(mH)) return;
- if ((**mH).meterVis) return;
- GetPort(&savePort);
- SetPort((**mH).meterOwner);
- (**mH).meterVis = TRUE;
- DrawMeterBackground(mH);
- for (i = inUpButton; i <= inPageDown; ++i)
- DrawTriangle(mH, i);
- DrawNeedle(mH);
- DrawSet(mH);
- ShowValue(mH, TRUE);
- SetPort(savePort);
- } /* end ShowMeter() */
-
- void DrawMeters(wPtr)
- WindowPtr wPtr;
- {
- int i;
- GrafPtr savePort;
- MeterHandle mH = (MeterHandle)(((WindowPeek)wPtr)->refCon);
-
- if (!ValidMeter(mH)) return;
- GetPort(&savePort);
- SetPort(wPtr);
- while (mH)
- {
- if ((**mH).meterVis)
- {
- DrawMeterBackground(mH);
- for (i = inUpButton; i <= inPageDown; ++i)
- DrawTriangle(mH, i);
- DrawNeedle(mH);
- DrawSet(mH);
- ShowValue(mH, TRUE);
- }
- mH = (**mH).nextMeter;
- }
- SetPort(savePort);
- } /* end DrawMeters() */
-
- void HiliteMeter(mH, hiliteState)
- MeterHandle mH;
- int hiliteState;
- {
- int i;
- GrafPtr savePort;
-
- if (!ValidMeter(mH)) return;
- if ((**mH).meterHilite == hiliteState) return;
- if ((**mH).meterHilite == 255 && hiliteState != 0) return;
- GetPort(&savePort);
- SetPort((**mH).meterOwner);
- if (inUpButton <= hiliteState && hiliteState <= inPageDown)
- {
- (**mH).meterHilite = hiliteState;
- DrawTriangle(mH, hiliteState);
- }
- else if (hiliteState == inBackground)
- { /* see #define at top of file */
- (**mH).meterHilite = hiliteState;
- ShowValue(mH, FALSE);
- }
- else if (hiliteState == 0) /* make normal */
- {
- if ((**mH).meterHilite == 255)
- {
- (**mH).meterHilite = 0;
- DrawMeterBackground(mH);
- for (i = inUpButton; i <= inPageDown; ++i)
- DrawTriangle(mH, i);
- DrawNeedle(mH);
- DrawSet(mH);
- ShowValue(mH, TRUE);
- }
- else if (inUpButton <= (**mH).meterHilite && (**mH).meterHilite <= inPageDown)
- {
- hiliteState = (**mH).meterHilite;
- (**mH).meterHilite = 0;
- DrawTriangle(mH, hiliteState);
- }
- else if ((**mH).meterHilite == inBackground)
- {
- (**mH).meterHilite = 0;
- ShowValue(mH, TRUE);
- }
- }
- else if (hiliteState == 255) /* make inactive */
- {
- (**mH).meterHilite = hiliteState;
- DrawMeterBackground(mH);
- }
- SetPort(savePort);
- } /* end HiliteMeter() */
-
- int FindMeter(thePoint, wPtr, mHP)
- Point thePoint;
- WindowPtr wPtr;
- MeterHandle *mHP;
- {
- int partCode;
- Boolean foundIt = FALSE;
- MeterHandle mH = (MeterHandle)(((WindowPeek)wPtr)->refCon);
-
- while (ValidMeter(mH))
- {
- if (PtInRect(thePoint, &((**mH).meterRect)))
- {
- foundIt = TRUE;
- break;
- }
- mH = (**mH).nextMeter;
- }
- if (foundIt && (partCode = TestMeter(mH, thePoint)))
- {
- *mHP = mH;
- return(partCode);
- }
- *mHP = NULL;
- return(0);
- } /* end FindMeter() */
-
- /* See ThumbControl() in MeterMain.c for an inside look at
- tracking a moving indicator. */
- int TrackMeter(mH, startPoint, actionProc)
- MeterHandle mH;
- Point startPoint;
- voidPtr actionProc;
- {
- int partCode;
- Point theMouse;
- Rect partRect, slopRect;
- Boolean pausing = FALSE;
-
- partCode = TestMeter(mH, startPoint);
- if (!partCode) return(0);
- if (inUpButton <= partCode && partCode <= inPageDown)
- {
- /* hilite part and call actionProc while mouse down in part */
- if (partCode == inUpButton)
- partRect = (**mH).incUpRect;
- else if (partCode == inDownButton)
- partRect = (**mH).incDownRect;
- else if (partCode == inPageUp)
- partRect = (**mH).pageUpRect;
- else if (partCode == inPageDown)
- partRect = (**mH).pageDownRect;
- slopRect = partRect;
- InsetRect(&slopRect, -10, -10);
- HiliteMeter(mH, partCode);
- while (StillDown())
- {
- GetMouse(&theMouse);
- if (PtInRect(theMouse, &slopRect))
- {
- if (pausing)
- {
- pausing = FALSE;
- HiliteMeter(mH, partCode);
- }
- if (actionProc)
- (*actionProc)(mH, partCode);
- }
- else
- {
- if (!pausing)
- {
- pausing = TRUE;
- HiliteMeter(mH, 0);
- }
- }
- }
- if (!pausing)
- HiliteMeter(mH, 0);
- }
- else if (partCode == inBackground)
- {
- ShowValue(mH, FALSE);
- while (StillDown())
- {
- if (actionProc)
- (*actionProc)();
- }
- ShowValue(mH, TRUE);
- }
- else return(0);
-
- } /* end TrackMeter() */
-
- int TestMeter(mH, thePoint)
- MeterHandle mH;
- Point thePoint;
- {
- int partCode;
-
- if (!ValidMeter(mH)) return(0);
- if (PtInRect(thePoint, &((**mH).meterRect)))
- {
- if ((**mH).meterVis && ((**mH).meterHilite != 255))
- {
- if (PtInRect(thePoint, &((**mH).incUpRect)))
- partCode = inUpButton;
- else if (PtInRect(thePoint, &((**mH).incDownRect)))
- partCode = inDownButton;
- else if (PtInRect(thePoint, &((**mH).pageUpRect)))
- partCode = inPageUp;
- else if (PtInRect(thePoint, &((**mH).pageDownRect)))
- partCode = inPageDown;
- else
- partCode = inBackground;
- return(partCode);
- }
- }
- return(0);
- } /* end TestMeter() */
-
- void MoveMeter(mH, h, v)
- MeterHandle mH;
- int h,v;
- {
- Boolean wasVisible = (**mH).meterVis;
-
- if (!ValidMeter(mH)) return;
- if (wasVisible)
- HideMeter(mH);
- OffsetRect(&((**mH).meterRect), h, v);
- OffsetRect(&((**mH).incDownRect), h, v);
- OffsetRect(&((**mH).incUpRect), h, v);
- OffsetRect(&((**mH).pageDownRect), h, v);
- OffsetRect(&((**mH).pageUpRect), h, v);
- OffsetRect(&((**mH).displayRect), h, v);
- (**mH).dialCentre.h += h;
- (**mH).dialCentre.v += v;
- if (wasVisible)
- ShowMeter(mH);
- } /* end MoveMeter() */
-
- void DragMeter(mH, startPoint, limitRect, slopRect, axis)
- MeterHandle mH;
- Point startPoint;
- Rect *limitRect;
- Rect *slopRect;
- int axis;
- {
- long posOffset;
- int h,v;
- Rect mRect, tRect;
- GrafPtr savePort;
- RgnHandle tempRgn;
-
- if (!ValidMeter(mH)) return;
- GetPort(&savePort);
- SetPort((**mH).meterOwner);
- tempRgn = NewRgn();
- mRect = (**mH).meterRect;
- mRect.bottom -= TITLEHEIGHT;
- tRect.left = (**mH).meterRect.left + 2;
- tRect.right = (**mH).meterRect.right - 2;
- tRect.bottom = (**mH).meterRect.bottom - 2;
- tRect.top = tRect.bottom - TITLEHEIGHT + 4;
-
- OpenRgn();
- FrameRoundRect(&mRect,mRect.right/10, mRect.bottom/10);
- FrameRect(&tRect);
- CloseRgn(tempRgn);
-
- posOffset = DragGrayRgn(tempRgn,startPoint,limitRect,slopRect,axis,0L);
- DisposeRgn(tempRgn);
- v = HiWord(posOffset);
- h = LoWord(posOffset);
- if (v != -32768 && h != -32768)
- MoveMeter(mH, h, v);
- SetPort(savePort);
- } /* end DragMeter() */
-
- /* Meter proportions are fixed - width determines height. */
- void SizeMeter(mH, w)
- MeterHandle mH;
- int w;
- {
- PicHandle tempPH;
- PolyHandle tempPoly;
- Boolean wasVisible = (**mH).meterVis;
-
- if (!ValidMeter(mH)) return;
- if (wasVisible)
- HideMeter(mH);
- /* gut the meter and recreate it */
- tempPH = (**mH).backgroundH;
- KillPicture(tempPH);
- tempPoly = (**mH).incUpH;
- KillPoly(tempPoly);
- tempPoly = (**mH).incDownH;
- KillPoly(tempPoly);
- tempPoly = (**mH).pageUpH;
- KillPoly(tempPoly);
- tempPoly = (**mH).pageDownH;
- KillPoly(tempPoly);
- (**mH).meterRect.right = (**mH).meterRect.left + w;
- CreateMeterBackground(mH);
- if (wasVisible)
- ShowMeter(mH);
- } /* end SizeMeter() */
-
- void SetMtrValue(mH, meterValue)
- MeterHandle mH;
- long meterValue;
- {
- GrafPtr savePort;
-
- if (!ValidMeter(mH)) return;
- GetPort(&savePort);
- SetPort((**mH).meterOwner);
- DrawSet(mH); /* erases old pointer */
- /* pin value to range min:max */
- if (meterValue < (**mH).meterMin)
- meterValue = (**mH).meterMin;
- else if (meterValue > (**mH).meterMax)
- meterValue = (**mH).meterMax;
- (**mH).meterValue = meterValue;
- DrawSet(mH);
- ShowValue(mH, FALSE);
- SetPort(savePort);
- } /* end SetMtrValue() */
-
- long GetMtrValue(mH)
- MeterHandle mH;
- {
-
- if (!ValidMeter(mH)) return(0L);
- return((**mH).meterValue);
- } /* end GetMtrValue() */
-
- void SetMtrMin(mH, minValue)
- MeterHandle mH;
- long minValue;
- {
- GrafPtr savePort;
-
- if (!ValidMeter(mH)) return;
- GetPort(&savePort);
- SetPort((**mH).meterOwner);
- DrawSet(mH); /* erases old pointer */
- DrawNeedle(mH); /* ditto needle */
- if (minValue >= (**mH).meterMax)
- {
- (**mH).meterMin = (**mH).meterMax;
- HiliteMeter(mH, 255); /* inactive - see IM 1-327 */
- return;
- }
- (**mH).meterMin = minValue;
- if ((**mH).meterValue < minValue)
- (**mH).meterValue = minValue;
- SetDisplayDivisor(mH);
- DrawSet(mH);
- DrawNeedle(mH);
- ShowValue(mH, FALSE);
- SetPort(savePort);
- } /* end SetMtrMin() */
-
- long GetMtrMin(mH)
- MeterHandle mH;
- {
-
- if (!ValidMeter(mH)) return(0L);
- return((**mH).meterMin);
- } /* end GetMtrMin() */
-
- void SetMtrMax(mH, maxValue)
- MeterHandle mH;
- long maxValue;
- {
- GrafPtr savePort;
-
- if (!ValidMeter(mH)) return;
- GetPort(&savePort);
- SetPort((**mH).meterOwner);
- DrawSet(mH); /* erases old pointer */
- DrawNeedle(mH); /* ditto needle */
- if (maxValue <= (**mH).meterMin)
- {
- (**mH).meterMax = (**mH).meterMin;
- HiliteMeter(mH, 255); /* inactive - see IM 1-327 */
- return;
- }
- (**mH).meterMax = maxValue;
- if ((**mH).meterValue > maxValue)
- (**mH).meterValue = maxValue;
- SetDisplayDivisor(mH);
- DrawSet(mH);
- DrawNeedle(mH);
- ShowValue(mH, FALSE);
- SetPort(savePort);
- } /* end SetMtrMax() */
-
- long GetMtrMax(mH)
- MeterHandle mH;
- {
-
- if (!ValidMeter(mH)) return(0L);
- return((**mH).meterMax);
- } /* end GetMtrMax() */
-
- void SetMRefCon(mH, refCon)
- MeterHandle mH;
- long refCon;
- {
-
- if (!ValidMeter(mH)) return;
- (**mH).meterRfCon = refCon;
- } /* end SetMRefCon() */
-
- long GetMRefCon(mH)
- MeterHandle mH;
- {
-
- if (!ValidMeter(mH)) return(0L);
- return((**mH).meterRfCon);
- } /* end GetMRefCon() */
-
- void SetNeedleValue(mH, value)
- MeterHandle mH;
- long value;
- {
- GrafPtr savePort;
-
- if (!ValidMeter(mH)) return;
- if ((**mH).needleValue == value) return;
- GetPort(&savePort);
- SetPort((**mH).meterOwner);
- DrawNeedle(mH); /* erases old needle */
- /* pin value to range min:max */
- if (value < (**mH).meterMin)
- value = (**mH).meterMin;
- else if (value > (**mH).meterMax)
- value = (**mH).meterMax;
- (**mH).needleValue = value;
- DrawNeedle(mH);
- ShowValue(mH, TRUE);
- SetPort(savePort);
- } /* end SetNeedleValue() */
-
- long GetNeedleValue(mH)
- MeterHandle mH;
- {
-
- if (!ValidMeter(mH)) return(0L);
- return((**mH).needleValue);
- } /* end GetNeedleValue() */
-
- long GetDisplayDivisor(mH)
- MeterHandle mH;
- {
-
- if (!ValidMeter(mH)) return(0L);
- return((**mH).displayDivisor);
- } /* end GetDisplayDivisor() */
-
- Boolean ValidMeter(mH)
- MeterHandle mH;
- {
-
- if (mH && (**mH).hasMeterID == HASMETER)
- return(TRUE);
- return(FALSE);
- } /* end ValidMeter() */
-
- int GetMaxTitlePixels(mH)
- MeterHandle mH;
- {
-
- if (!ValidMeter(mH)) return(0);
- return((**mH).meterRect.right - (**mH).meterRect.left - 4);
- } /* end GetMaxTitlePixels() */
-
- /* A meter, like a scroll bar, is very attached to its owning
- window. Only MeterSnapShot() will allow you to draw a meter
- in another grafPort. Set the port, and set the font in the port
- to something appropriate for the meter title before the call. */
- void MeterSnapshot(mH)
- MeterHandle mH;
- {
- int i;
- Byte mVis, mHilite;
-
- if (!ValidMeter(mH)) return;
- mVis = (**mH).meterVis;
- mHilite = (**mH).meterHilite;
- (**mH).meterVis = TRUE;
- (**mH).meterHilite = 0;
- DrawMeterBackground(mH);
- for (i = inUpButton; i <= inPageDown; ++i)
- DrawTriangle(mH, i);
- DrawNeedle(mH);
- DrawSet(mH);
- ShowValue(mH, TRUE);
- (**mH).meterVis = mVis;
- (**mH).meterHilite = mHilite;
- } /* end MeterSnapshot() */
-
- /* Functions used only in this file from here on */
-
- /* Load up a table of sines to avoid going off on a tangent (sorry).
- If this table were entered by hand, <math.h> would not be needed. */
- void InitMeters()
- {
- int i;
- double x;
-
- for (i = 0; i <= 90; ++i)
- {
- x = ((double)i*PI)/180.0; /* convert degrees to radians */
- sineTable[i] = (int)(sin(x)*1000.0);
- }
- } /* end InitMeters() */
-
-
- /* The real fun - create the meter background picture
- and set up points and rects needed for drawing it. We could
- also have created the background in a drafting program and
- just scale it to the meter's rectangle, but this wouldn't be
- as precise or as easy to modify. */
- void CreateMeterBackground(mH)
- MeterHandle mH;
- {
- int i, j, k, h, v, posInc;
- long theSin, theCos;
- long radius, xo, yo, lowestTickH, lowestTickV;
- Rect boundRect, theClipRect, tempRect, innerCircle;
- GrafPtr savePort;
- RgnHandle clpRgn, dialRgn, innerTickRgn;
- PenState pState;
- PicHandle tempPicH;
- PolyHandle tempPoly;
- Point c, l, r; /* centre, left, right of polygons */
-
- GetPort(&savePort);
- SetPort((**mH).meterOwner);
- /* adjust meterRect - meter proportions are fixed, meterRect.bottom is ignored */
- boundRect = (**mH).meterRect;
- if (boundRect.right - boundRect.left < MINWIDTH)
- boundRect.right = boundRect.left + MINWIDTH;
- boundRect.bottom = boundRect.top + ((boundRect.right - boundRect.left)*TVHRATIO)/1000;
- tempRect = boundRect;
- boundRect.bottom += TITLEHEIGHT;
- (**mH).meterRect = boundRect;
- /* first adjust the clip; */
- clpRgn = NewRgn();
- dialRgn = NewRgn();
- innerTickRgn = NewRgn();
- GetClip(clpRgn);
- /* then draw meter in rectangle starting at 0,0 for convenience */
- OffsetRect(&boundRect,-boundRect.left, -boundRect.top);
- OffsetRect(&tempRect,-tempRect.left, -tempRect.top);
- theClipRect = boundRect;
- theClipRect.right += 100;
- theClipRect.bottom += 200;
- ClipRect(&theClipRect);
- GetPenState(&pState);
- tempPicH = OpenPicture(&boundRect);
- PenNormal();
- /* draw black rounded rect */
- FillRoundRect(&tempRect,tempRect.right/10, tempRect.right/10,black);
- i = tempRect.bottom;
- /* and frame two white circles */
- tempRect.bottom = tempRect.right; /* square it off */
- InsetRect(&tempRect, tempRect.right/15, tempRect.right/15);
- j = tempRect.bottom;
- FillOval(&tempRect, white);
- InsetRect(&tempRect, 3, 3);
- radius = (tempRect.right - tempRect.left)/2;
- (**mH).dialCentre.h = tempRect.left + radius;
- (**mH).dialCentre.v = tempRect.top + radius;
- FrameOval(&tempRect);
- OpenRgn();
- FrameOval(&tempRect);
- CloseRgn(dialRgn);
- k = radius - (radius*INNERPCT + 50L)/100L;
- InsetRect(&tempRect, k, k);
- innerCircle = tempRect;
- OpenRgn();
- FrameOval(&tempRect);
- CloseRgn(innerTickRgn);
- DiffRgn(dialRgn, innerTickRgn, dialRgn); /* that made a ring */
- DisposeRgn(innerTickRgn);
- /* white out rect for control triangles */
- tempRect.top = j + j/20; /* j = bottom of larger dial circle */
- tempRect.left = (**mH).dialCentre.h - radius;
- tempRect.bottom = i - j/20; /* i = bottom of rounded rect */
- tempRect.right = (**mH).dialCentre.h + radius;
- i = j = tempRect.right - tempRect.left;
- i = (i/4)*4;
- tempRect.left += (j -i)/2;
- tempRect.right = tempRect.left + i;
- FillRect(&tempRect, white);
- /* put lines between the control triangles */
- MoveTo(tempRect.left + i/4, tempRect.top);
- Line(0, tempRect.bottom - tempRect.top);
- MoveTo(tempRect.left + i/2, tempRect.top);
- Line(0, tempRect.bottom - tempRect.top);
- MoveTo(tempRect.left + i/4 + i/2, tempRect.top);
- Line(0, tempRect.bottom - tempRect.top);
- tempRect.right = tempRect.left + i/4;
- (**mH).pageDownRect = tempRect;
- OffsetRect(&tempRect, i/4, 0);
- (**mH).incDownRect = tempRect;
- OffsetRect(&tempRect, i/4, 0);
- (**mH).incUpRect = tempRect;
- OffsetRect(&tempRect, i/4, 0);
- (**mH).pageUpRect = tempRect;
- SetClip(dialRgn);
- /* dialRgn is the ring for the ticks */
- PenSize(2,2);
- /* Draw the major ticks around circumference of dial */
- h = (**mH).dialCentre.h;
- v = (**mH).dialCentre.v;
- if (NUMTICKS >= 3)
- {
- posInc = 2500/(NUMTICKS - 1);
- for (j = -1250; j <= 1250; j += posInc)
- {
- i = j/10;
- GetSinAndCos(i, &theSin, &theCos);
- xo = (radius*theSin + 500L)/1000L + h;
- yo = (-radius*theCos + 500L)/1000L + v;
- MoveTo(h - 1, v - 1);
- LineTo(xo - 1, yo - 1);
- }
- }
- /* and now the minor ticks */
- PenSize(1,1);
- if (NUMMINORTICKS >= 3)
- {
- posInc = 2500/(NUMMINORTICKS - 1);
- for (j = -1250; j <= 1250; j += posInc)
- {
- i = j/10;
- /* determine sine and cosine to use */
- GetSinAndCos(i, &theSin, &theCos);
- xo = (radius*theSin + 500L)/1000L + h;
- yo = (-radius*theCos + 500L)/1000L + v;
- MoveTo(h - 1, v - 1);
- LineTo(xo - 1, yo - 1);
- }
- }
-
- ClipRect(&theClipRect);
- DisposeRgn(dialRgn);
- /* White out centre - needed for clipboard copying. */
- FillOval(&innerCircle, white);
- /* put small black circle in centre of dial */
- tempRect.top = (**mH).dialCentre.v - CENTRERADIUS;
- tempRect.left = (**mH).dialCentre.h - CENTRERADIUS;
- tempRect.bottom = (**mH).dialCentre.v + CENTRERADIUS;
- tempRect.right = (**mH).dialCentre.h + CENTRERADIUS;
- FillOval(&tempRect, black);
- /* set up and draw displayRect just below dial centre */
- lowestTickH = ((xo - h)*INNERPCT)/100L + h;
- lowestTickV = ((yo - v)*INNERPCT)/100L + v;
- tempRect.right = lowestTickH -2160/((**mH).meterRect.right - (**mH).meterRect.left);
- tempRect.left = tempRect.right - 2*(tempRect.right - h);
- tempRect.top = (int)lowestTickV;
- tempRect.bottom = tempRect.top + 16;
- (**mH).displayRect = tempRect;
- AdjustDisplay(mH);
- tempRect = (**mH).displayRect;
- OffsetRect(&tempRect, -1, 0);
- FrameRect(&tempRect);
- MoveTo(tempRect.left + 1, tempRect.bottom);
- LineTo(tempRect.right, tempRect.bottom);
- MoveTo(tempRect.right, tempRect.top + 1);
- LineTo(tempRect.right, tempRect.bottom);
- InsetRect(&tempRect, 1, 1);
- i = (**mH).meterRect.left;
- j = (**mH).meterRect.top;
- OffsetRect(&tempRect, i,j);
- (**mH).displayRect = tempRect;
- SetDisplayDivisor(mH);
- ClosePicture();
- (**mH).backgroundH = tempPicH;
- /* define up and down arrows as triangular polygons */
- /* page up poly */
- tempRect = (**mH).pageUpRect;
- l.h = tempRect.left + (tempRect.right -tempRect.left)/8;
- r.h = tempRect.right - (tempRect.right -tempRect.left)/8;
- i = r.h - l.h; /* side length of triangle */
- i = (i/2)*2;
- r.h = l.h + i;
- j = (i*PGPOLYHEIGHT + 1000)/2000; /* vertical height, 1/2side * root3 */
- c.v = tempRect.top + (tempRect.bottom - tempRect.top - j)/2;
- c.h = tempRect.left + (tempRect.right - tempRect.left)/2;
- l.v = c.v + j;
- r.v = c.v + j;
- tempPoly = OpenPoly();
- MoveTo(c.h, c.v);
- LineTo(l.h, l.v);
- LineTo(r.h, r.v);
- LineTo(c.h, c.v);
- ClosePoly();
- (**mH).pageUpH = tempPoly;
- /* inc up poly */
- tempRect = (**mH).incUpRect;
- l.h = tempRect.left + (tempRect.right - tempRect.left)/4;
- r.h = tempRect.right - (tempRect.right - tempRect.left)/4;
- i = r.h - l.h; /* side length of triangle */
- i = (i/2)*2;
- r.h = l.h + i;
- j = (i*INCPOLYHEIGHT + 1000)/2000; /* vertical height, 1/2side * root3 */
- c.v = tempRect.top + (tempRect.bottom - tempRect.top - j)/2;
- c.h = tempRect.left + (tempRect.right - tempRect.left)/2;
- l.v = c.v + j;
- r.v = c.v + j;
- tempPoly = OpenPoly();
- MoveTo(c.h, c.v);
- LineTo(l.h, l.v);
- LineTo(r.h, r.v);
- LineTo(c.h, c.v);
- ClosePoly();
- (**mH).incUpH = tempPoly;
- /* inc down poly */
- tempRect = (**mH).incDownRect;
- l.h = tempRect.left + (tempRect.right - tempRect.left)/4;
- r.h = tempRect.right - (tempRect.right - tempRect.left)/4;
- i = r.h - l.h; /* side length of triangle */
- i = (i/2)*2;
- r.h = l.h + i;
- j = (i*INCPOLYHEIGHT + 1000)/2000; /* vertical height, 1/2side * root3 */
- c.v = tempRect.top + (tempRect.bottom - tempRect.top - j)/2 + j;
- c.h = tempRect.left + (tempRect.right - tempRect.left)/2;
- l.v = c.v - j;
- r.v = c.v - j;
- tempPoly = OpenPoly();
- MoveTo(c.h, c.v);
- LineTo(l.h, l.v);
- LineTo(r.h, r.v);
- LineTo(c.h, c.v);
- ClosePoly();
- (**mH).incDownH = tempPoly;
- /* page down poly */
- tempRect = (**mH).pageDownRect;
- l.h = tempRect.left + (tempRect.right -tempRect.left)/8;
- r.h = tempRect.right - (tempRect.right -tempRect.left)/8;
- i = r.h - l.h; /* side length of triangle */
- i = (i/2)*2;
- r.h = l.h + i;
- j = (i*PGPOLYHEIGHT + 1000)/2000; /* vertical height, 1/2side * root3 */
- c.v = tempRect.top + (tempRect.bottom - tempRect.top - j)/2 + j;
- c.h = tempRect.left + (tempRect.right - tempRect.left)/2;
- l.v = c.v - j;
- r.v = c.v - j;
- tempPoly = OpenPoly();
- MoveTo(c.h, c.v);
- LineTo(l.h, l.v);
- LineTo(r.h, r.v);
- LineTo(c.h, c.v);
- ClosePoly();
- (**mH).pageDownH = tempPoly;
-
- /* set up needle and set point parameters */
- radius = (radius*(INNERPCT-2L) + 50L)/100;
- (**mH).needleLong = radius;
- (**mH).setLong = radius;
- (**mH).needleShort = (lowestTickV - (**mH).dialCentre.v)/2;
- (**mH).setShort = (**mH).needleShort;
- (**mH).halfNeedleWidth = radius/HALFNEEDLERATIO;
-
- /* move rects and points to proper position */
- i = (**mH).meterRect.left;
- j = (**mH).meterRect.top;
- OffsetRect(&((**mH).incDownRect), i,j);
- OffsetRect(&((**mH).incUpRect), i,j);
- OffsetRect(&((**mH).pageDownRect), i,j);
- OffsetRect(&((**mH).pageUpRect), i,j);
- (**mH).dialCentre.h += i;
- (**mH).dialCentre.v += j;
- /* clean up on the way out */
- SetPenState(&pState);
- SetClip(clpRgn);
- DisposeRgn(clpRgn);
- SetPort(savePort);
- } /* end CreateMeterBackground() */
-
- void DrawMeterBackground(mH)
- MeterHandle mH;
- {
- PicHandle tempPH = (**mH).backgroundH;
- Rect tempRect;
- PenState pState;
-
- GetPenState(&pState);
- PenNormal();
- tempRect = (**mH).meterRect;
- EraseRect(&tempRect);
- if ((**mH).meterVis)
- {
- if ((**mH).meterHilite != 255)
- DrawPicture(tempPH, &tempRect);
- else
- DrawInactiveMeter(mH);
- DrawMeterTitle(mH);
- }
- SetPenState(&pState);
- } /* end DrawMeterBackground() */
-
- /* Title is centered and truncated if necessary, in whatever
- font is current. Drawing is clipped to the intersection of
- the title rect and the current clip region. */
- void DrawMeterTitle(mH)
- MeterHandle mH;
- {
- int i,j, height;
- Rect tempRect;
- char title[32];
- FontInfo tempInfo;
- PenState pState;
- RgnHandle oldClipRgn, titleClipRgn;
- ControlHandle cHH, cHV;
- char *mTPtr = (**mH).title;
-
- GetFontInfo(&tempInfo);
- height = tempInfo.ascent + tempInfo.descent + tempInfo.leading;
- /* copy title - text must not be referenced by
- an unlocked handle when calling DrawString() */
- for (i = 0; i < 31; ++i)
- title[i] = mTPtr[i];
- /* draw shadowed title box, effective height =
- TITLEHEIGHT - 4, just below black rounded rect */
- tempRect.left = (**mH).meterRect.left + 2;
- tempRect.right = (**mH).meterRect.right - 2;
- tempRect.bottom = (**mH).meterRect.bottom - 2;
- tempRect.top = tempRect.bottom - TITLEHEIGHT + 4;
- FrameRect(&tempRect);
- MoveTo(tempRect.left + 1, tempRect.bottom);
- LineTo(tempRect.right, tempRect.bottom);
- MoveTo(tempRect.right, tempRect.top + 1);
- LineTo(tempRect.right, tempRect.bottom);
- i = StringWidth(title);
- j = tempRect.right - tempRect.left;
- if ((j - i) < 2) /* title too long - truncate */
- {
- while (StringWidth(title) > j - 2)
- title[0] -= 1;
- i = StringWidth(title);
- }
- GetFontInfo(&tempInfo);
- height = tempInfo.ascent + tempInfo.descent + tempInfo.leading;
- MoveTo(tempRect.left + (j - i)/2,
- tempRect.top + (tempRect.bottom - tempRect.top)/2 - height/2 + tempInfo.ascent);
- oldClipRgn = NewRgn();
- titleClipRgn = NewRgn();
- GetClip(oldClipRgn);
- RectRgn(titleClipRgn, &tempRect);
- SectRgn(titleClipRgn, oldClipRgn, titleClipRgn);
- SetClip(titleClipRgn);
- GetPenState(&pState);
- PenNormal();
-
- DrawString(title);
-
- SetPenState(&pState);
- SetClip(oldClipRgn);
- DisposeRgn(oldClipRgn);
- DisposeRgn(titleClipRgn);
- } /* end DrawMeterTitle() */
-
- /* The four triangles (two small, two large)
- correspond to the inc and page parts of a
- scroll bar. */
- void DrawTriangle(mH, partCode)
- MeterHandle mH;
- int partCode;
- {
- PenState pState;
- PolyHandle tempPoly;
-
- if ((**mH).meterHilite == 255) return;
- if (partCode == inUpButton)
- tempPoly = (**mH).incUpH;
- else if (partCode == inDownButton)
- tempPoly = (**mH).incDownH;
- else if (partCode == inPageUp)
- tempPoly = (**mH).pageUpH;
- else if (partCode == inPageDown)
- tempPoly = (**mH).pageDownH;
- else
- return;
- GetPenState(&pState);
- PenNormal();
- OffsetPoly(tempPoly, (**mH).meterRect.left, (**mH).meterRect.top);
- if (partCode == (**mH).meterHilite)
- {
- OffsetPoly(tempPoly, -1, -1);
- FillPoly(tempPoly, black);
- }
- else
- {/* neat way to shadow ANY polygon */
- FillPoly(tempPoly, black);
- FramePoly(tempPoly);
- OffsetPoly(tempPoly, -1, -1);
- ErasePoly(tempPoly);
- FramePoly(tempPoly);
- }
- OffsetPoly(tempPoly, -(**mH).meterRect.left + 1, -(**mH).meterRect.top + 1);
- SetPenState(&pState);
- } /* end DrawTriangle() */
-
- void DrawNeedle(mH)
- MeterHandle mH;
- {
- long l1, l2, l3, xa, xb, xc, xd;
- long theSin, theCos, ya, yb, yc, yd;
- int position;
- int h = (**mH).dialCentre.h;
- int v = (**mH).dialCentre.v;
- PenState pState;
- PolyHandle needlePoly;
-
- if (!((**mH).meterVis) || (**mH).meterHilite == 255) return;
- GetPenState(&pState);
- PenMode(patXor);
- PenPat(black);
- PenSize(1,1);
-
- /* Determine position of needle based on value. Position
- is the angle in degrees measured from 0 = straight up,
- increasing clockwise, range -125:+125 */
- position = (((**mH).needleValue - (**mH).meterMin)*250L)
- /((**mH).meterMax - (**mH).meterMin) - 125L;
- if (position < -125)
- position = -125;
- if (position > 125)
- position = 125;
- /* Determine sine and cosine to use. */
- GetSinAndCos(position, &theSin, &theCos);
- /* Calculate four vertices of needle indicator by
- changing from polar to rectangular coord's and
- then translating over to dial centre. */
- l1 = (**mH).needleLong;
- l2 = (**mH).needleShort;
- l3 = (**mH).halfNeedleWidth;
- xa = (-l2*theSin + 500L)/1000L + h;
- ya = (l2*theCos + 500L)/1000L + v;
- xb = (l1*theSin + 500L)/1000L + h;
- yb = (-l1*theCos + 500L)/1000L + v;
- xc = (-l3*theCos + 500L)/1000L + h;
- yc = (-l3*theSin + 500L)/1000L + v;
- xd = -xc + 2*h;
- yd = -yc + 2*v;
-
- needlePoly = OpenPoly();
- MoveTo(xa, ya);
- LineTo(xc, yc);
- LineTo(xb, yb);
- LineTo(xd, yd);
- LineTo(xa, ya);
- ClosePoly();
- PaintPoly(needlePoly);
- KillPoly(needlePoly);
-
- SetPenState(&pState);
- } /* end DrawNeedle() */
-
- void DrawSet(mH)
- MeterHandle mH;
- {
- long l1, l2, l3, xa, xb;
- long theSin, theCos, ya, yb;
- int position;
- int thePenSize = (**mH).halfSetWidth*2;
- int h = (**mH).dialCentre.h;
- int v = (**mH).dialCentre.v;
- PenState pState;
-
- if (!((**mH).meterVis) || (**mH).meterHilite == 255) return;
- GetPenState(&pState);
- PenMode(patXor);
- PenPat(black);
- PenSize(thePenSize,thePenSize);
-
- /* determine position of set indicator from value */
- position = (((**mH).meterValue - (**mH).meterMin)*250L)
- /((**mH).meterMax - (**mH).meterMin) - 125L;
- if (position < -125)
- position = -125;
- if (position > 125)
- position = 125;
-
- /* determine sine and cosine to use */
- GetSinAndCos(position, &theSin, &theCos);
-
- /* calculate two vertices of position indicator */
- l1 = (**mH).setLong;
- l2 = (**mH).setShort;
- l3 = (**mH).halfSetWidth;
- xa = (-l2*theSin + 500L)/1000L - HALFSETWIDTH + h;
- ya = (l2*theCos + 500L)/1000L - HALFSETWIDTH + v;
- xb = (l1*theSin + 500L)/1000L - HALFSETWIDTH + h;
- yb = (-l1*theCos + 500L)/1000L - HALFSETWIDTH + v;
-
- MoveTo(xa, ya);
- LineTo(xb, yb);
-
- SetPenState(&pState);
- } /* end DrawSet() */
-
- void ShowValue(mH, needle)
- MeterHandle mH;
- Boolean needle;
- {
- int i;
- int oldFont, oldSize;
- Style oldStyle;
- PenState pState;
- long theValue;
- Rect tempRect;
- char pNumStr[16]; /* pascal */
-
- if (!((**mH).meterVis) || (**mH).meterHilite == 255) return;
- GetPenState(&pState);
- PenNormal();
- oldFont = thePort->txFont;
- oldSize = thePort->txSize;
- oldStyle = thePort->txFace;
- TextFont(geneva);
- TextSize(12);
- TextFace(' ');
- if (needle)
- theValue = (**mH).needleValue;
- else
- theValue = (**mH).meterValue;
- /* Truncate value to fit display box. */
- if ((**mH).displayDivisor > 1L)
- theValue /= (**mH).displayDivisor;
- tempRect = (**mH).displayRect;
- NumToString(theValue, pNumStr);
- i = StringWidth(pNumStr);
- EraseRect(&tempRect);
- MoveTo(tempRect.right - i- 4,
- tempRect.top + (tempRect.bottom - tempRect.top)/2 + TEXTVOFFSET);
- DrawString(pNumStr);
- TextFont(oldFont);
- TextSize(oldSize);
- TextFace(oldStyle);
- SetPenState(&pState);
- } /* end ShowValue() */
-
- void DrawInactiveMeter(mH)
- MeterHandle mH;
- {
- Rect tempRect;
-
- tempRect = (**mH).meterRect;
- tempRect.bottom -= TITLEHEIGHT;
- FrameRoundRect(&tempRect,tempRect.right/10, tempRect.bottom/10);
- } /* end DrawInactiveMeter() */
-
- /* Ensure that digital display shows at least MINDIGITS and at most MAXDIGITS
- plus sign - called only during creation of background meter picture. */
- void AdjustDisplay(mH)
- MeterHandle mH;
- {
- int oldFont, oldSize;
- Style oldStyle;
- int displayWidth = (**mH).displayRect.right - (**mH).displayRect.left;
- int minusW, num4W;
- int numDisplayDigits, wantedWidth, halfWidthDiff;
-
- oldFont = thePort->txFont;
- oldSize = thePort->txSize;
- oldStyle = thePort->txFace;
- TextFont(geneva);
- TextSize(12);
- TextFace(' ');
- minusW = CharWidth('-');
- num4W = CharWidth('4');
- numDisplayDigits = (displayWidth - minusW - 8)/num4W;
- if (numDisplayDigits < MINDIGITS) /* too small */
- {
- wantedWidth = 8 + minusW + num4W*MINDIGITS;
- halfWidthDiff = (wantedWidth - displayWidth + 1)/2;
- (**mH).displayRect.left -= halfWidthDiff;
- (**mH).displayRect.right += halfWidthDiff;
- }
- else if (numDisplayDigits > MAXDIGITS) /* too big */
- {
- wantedWidth = 8 + minusW + num4W*MAXDIGITS;
- halfWidthDiff = (displayWidth - wantedWidth -1)/2;
- (**mH).displayRect.left += halfWidthDiff;
- (**mH).displayRect.right -= halfWidthDiff;
- }
- TextFont(oldFont);
- TextSize(oldSize);
- TextFace(oldStyle);
- } /* end AdjustDisplay() */
-
- /* Set displayDivisor to appropriate power of ten so that as many digits
- as possible are shown in the display. Called when creating meter and
- also when setting meter max or min */
- void SetDisplayDivisor(mH)
- MeterHandle mH;
- {
- int oldFont, oldSize;
- Style oldStyle;
- int displayWidth = (**mH).displayRect.right - (**mH).displayRect.left + 2;
- int minusW, num4W, numDisplayDigits, wantToDisplay, power;
- long absMin, absMax;
- char pNumStr[16]; /* pascal */
-
- oldFont = thePort->txFont;
- oldSize = thePort->txSize;
- oldStyle = thePort->txFace;
- TextFont(geneva);
- TextSize(12);
- TextFace(' ');
- minusW = CharWidth('-');
- num4W = CharWidth('4');
- numDisplayDigits = (displayWidth - minusW - 8)/num4W;
- absMin = ((**mH).meterMin < 0) ? - (**mH).meterMin : (**mH).meterMin;
- absMax = ((**mH).meterMax < 0) ? - (**mH).meterMax : (**mH).meterMax;
- if (absMin > absMax)
- absMax = absMin;
- NumToString(absMax, pNumStr);
- wantToDisplay = (int)(pNumStr[0]);
- if (wantToDisplay > numDisplayDigits) /* too many, must scale value down */
- {
- /* divisor = 10 raised to power (wantToDisplay - numDisplayDigits) */
- power = wantToDisplay - numDisplayDigits;
- (**mH).displayDivisor = 10L;
- while (--power > 0)
- (**mH).displayDivisor *= 10L;
- }
- else /* no scaling necessary */
- (**mH).displayDivisor = 1L;
- TextFont(oldFont);
- TextSize(oldSize);
- TextFace(oldStyle);
- } /* end SetDisplayDivisor() */
-
- /* Position is interpreted as an angle in degrees. The
- values are retrieved from sineTable[], which is an array
- of integers recording sines from 0 to 90 degrees, scaled
- up by 1000. */
- void GetSinAndCos(position, theSin, theCos)
- int position;
- long *theSin, *theCos;
- {
-
- if (position < -125 || position > 125)
- {
- *theSin = 0L;
- *theCos = 0L;
- return;
- }
- else if (-125 <= position && position <= -90)
- {
- *theSin = -sineTable[position + 180];
- *theCos = -sineTable[-position - 90];
- }
- else if (-90 < position && position <= 0)
- {
- *theSin = -sineTable[-position];
- *theCos = sineTable[position + 90];
- }
- else if (0 < position && position <= 90)
- {
- *theSin = sineTable[position];
- *theCos = sineTable[90 - position];
- }
- else /* 90:125 */
- {
- *theSin = sineTable[180 - position];
- *theCos = -sineTable[position - 90];
- }
- } /* end GetSinAndCos() */